﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Nexterday.Linq.Autocompiler.EF4;
using Nexterday.Linq.Autocompiler.EF4.Tests;

namespace Nexterday.Linq.Autocompiler.E4.Tests
{
    [TestFixture]
    public class ParametrizationTests
    {
        [Test]
        public void Executing_Identical_Queries_Calls_Cache_With_Same_Key()
        {
            var testCache=GetTestCache();
            using (NorthwindEntities db = new NorthwindEntities())
            {
                int productId1 = 1;
                int productId2 = 1;

                var product = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == productId1 select p).Single();
                var product2 = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == productId2 select p).Single();
                Assert.AreEqual(1, product.ProductID);
                Assert.AreEqual(1, product2.ProductID);
                Assert.AreEqual(2, testCache.Keys.Count);
                Assert.AreEqual(1, testCache.Keys.Distinct().Count());

            }
        }

        [Test]
        public void Executing_Same_Query_With_Different_Parameters_Calls_Cache_With_Same_Key()
        {
            var testCache = GetTestCache();
            using (NorthwindEntities db = new NorthwindEntities())
            {
                int productId1 = 1;
                int productId2 = 2;//Different!

                var product = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == productId1 select p).Single();
                var product2 = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == productId2 select p).Single();
                Assert.AreEqual(1, product.ProductID);
                Assert.AreEqual(2, product2.ProductID);
                Assert.AreEqual(2, testCache.Keys.Count);
                Assert.AreEqual(1, testCache.Keys.Distinct().Count());//Still only one!
            }
        }

        [Test]
        public void Executing_Same_Query_With_Different_Constants_Calls_Cache_With_Different_Keys()
        {
            var testCache = GetTestCache();
            using (NorthwindEntities db = new NorthwindEntities())
            {
                
                var product = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == 1 select p).Single();
                var product2 = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache }) where p.ProductID == 2 select p).Single();
                Assert.AreEqual(1, product.ProductID);
                Assert.AreEqual(2, product2.ProductID);
                Assert.AreEqual(2, testCache.Keys.Count);
                Assert.AreEqual(2, testCache.Keys.Distinct().Count());
            }
        }

        [Test]
        public void Executing_Same_Query_With_Different_Constants_Calls_Cache_With_Same_Key_When_ParametrizePrimitiveConstants_Is_True()
        {
            var testCache = GetTestCache();
            using (NorthwindEntities db = new NorthwindEntities())
            {

                var product = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache ,ParametrizePrimitiveConstants=true}) where p.ProductID == 1 select p).Single();
                var product2 = (from p in db.Products.AsCompilable(new CompilationParameters { CacheFactoryDelegate = () => testCache, ParametrizePrimitiveConstants = true }) where p.ProductID == 2 select p).Single();
                Assert.AreEqual(1, product.ProductID);
                Assert.AreEqual(2, product2.ProductID);
                Assert.AreEqual(2, testCache.Keys.Count);
                Assert.AreEqual(1, testCache.Keys.Distinct().Count());
            }
        }


        private NullCompiledQueryCache GetTestCache()
        {
            return new NullCompiledQueryCache();
        }
    }
}
